﻿#include "description.h"
#include <QDebug>
#include <QCoreApplication>
#include <QFile>
#include <QThreadPool>
#include "rs232device.h"
#include "ethernetdevice.h"
#include "jakarobotdevice.h"
//#include "auborobotdevice.h"
#include "delayoperation.h"
#include "wordopcontrolledoperation.h"
#include "movejointoperation.h"
#include "snapoperation.h"
#include "recognizeoperation.h"
#include "step.h"
#include "virtualdevice.h"
#include "dahengcameradevice.h"
#include "RecognizeDevice.h"
#include "../task/stepsthread.h"

Description::Description() : m_isAllInitialized(false),m_isRunning(false) {
    InitObjectFactory();
}

Description& Description::operator=(Description& description){
    // 清除m_pDevices及包含的内容
    for(int i = m_pDevices.count() - 1; i >= 0; i--){
        Device* pDevice = m_pDevices.at(i);
        delete pDevice;
        m_pDevices.removeLast();
    }

    for(int i = 0; i < description.GetDevices().count();i++){
        Device* pDevice = description.GetDevices().at(i);
        Device *pNewDevice = (Device *) ObjectFactory::createObject(pDevice->getClassName().toLatin1(),this);

        pNewDevice->clone(pDevice);

        m_pDevices.append(pNewDevice);
    }

    // 清除m_pSequences及包含的内容
    for(int i = m_pSequences.count() - 1; i >= 0; i--){
        Sequence* pSequence = m_pSequences.at(i);

        QList<Step*> steps = pSequence->GetSteps();
        for(int j = steps.count() - 1; j >= 0; j--){
            Step* pStep = steps.at(j);

            QList<Operation*> operations = pStep->GetOperations();
            for(int k = operations.count() - 1; k >= 0; k--){
                Operation* pOperation = operations.at(k);

                delete pOperation;
                operations.removeLast();
            }
            delete pStep;
            steps.removeLast();
        }
        delete pSequence;
        m_pSequences.removeLast();
    }

    for(int i = 0; i < description.GetSequences().count();i++){
        Sequence* pSequence = description.GetSequences().at(i);
        Sequence *pNewSequence = new Sequence();

        (*pNewSequence) = (*pSequence);

        m_pSequences.append(pNewSequence);
    }

    return *this;
}

QList<Device *> Description::pDevices() const
{
    return m_pDevices;
}

QList<Sequence *> Description::pSequences() const
{
    return m_pSequences;
}

void Description::clear(){
    m_pDevices.clear();
    m_pSequences.clear();
}

void Description::InitObjectFactory(){
    ObjectFactory::registerClass<DelayOperation>();
    ObjectFactory::registerClass<WordopControlLEDOperation>();
    ObjectFactory::registerClass<MoveJointOperation>();
    ObjectFactory::registerClass<RS232Device>();
    ObjectFactory::registerClass<EthernetDevice>();
    ObjectFactory::registerClass<JakaRobotDevice>();
    //ObjectFactory::registerClass<AuboRobotDevice>();
    ObjectFactory::registerClass<DahengCameraDevice>();
    ObjectFactory::registerClass<RecognizeDevice>();
    ObjectFactory::registerClass<VirtualDevice>();
    ObjectFactory::registerClass<Sequence>();
    ObjectFactory::registerClass<Step>();
    ObjectFactory::registerClass<SnapOperation>();
    ObjectFactory::registerClass<RecognizeOperation>();
}

bool Description::writeXML(const QString &filePath)
{
    QFile file(filePath);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
        qWarning() << "Unable to open file:" << filePath;
        return false;
    }

    QXmlStreamWriter xmlWriter(&file);
    xmlWriter.setAutoFormatting(true);

    xmlWriter.writeStartDocument();
    xmlWriter.writeStartElement("Description");
    //////////////////////////////////////////////////////////////
    /// 开始写入内容 devices
    xmlWriter.writeStartElement("Devices");
    foreach (Device *pDevice, m_pDevices) {
        pDevice->writeXML(xmlWriter);
    }
    xmlWriter.writeEndElement();
    //////////////////////////////////////////////////////////////
    /// 开始写入内容 sequences
    xmlWriter.writeStartElement("Sequences");
    foreach (Sequence *pSequence, m_pSequences) {
        pSequence->writeXML(xmlWriter);
    }
    xmlWriter.writeEndElement();
    /////////////////////////////////////////////////////////////
    xmlWriter.writeEndElement();
    xmlWriter.writeEndDocument();

    file.close();
    return true;
}

bool Description::ReadXML(const QString &filePath)
{
    QList<QString> toolsList;
    QFile file(filePath);

    if (!file.open(QIODevice::ReadOnly)) {
        qWarning() << "Unable to open file:" << filePath;
        return false;
    }

    QXmlStreamReader xmlReader(&file);

    // 读取 XML 直到结束
    while (!xmlReader.atEnd() && !xmlReader.hasError()) {
        xmlReader.readNext();

        // 如果是 Description 元素的开始
        if (xmlReader.isStartElement() && xmlReader.name() == QStringLiteral("Description")) {
            // 读取 description 元素内部
            while (!(xmlReader.tokenType() == QXmlStreamReader::EndElement
                     && xmlReader.name() == QStringLiteral("Description"))) {
                xmlReader.readNext();

                if (xmlReader.isStartElement() && xmlReader.name() == QStringLiteral("Devices")) {
                    while (!(xmlReader.tokenType() == QXmlStreamReader::EndElement
                             && xmlReader.name() == QStringLiteral("Devices"))) {
                        xmlReader.readNext();
                        if (xmlReader.isStartElement()) {
                            QString className = xmlReader.name().toString();
                            Device *pDevice = (Device *) ObjectFactory::createObject(
                                className.toLatin1(),this);
                            if (pDevice != NULL) {
                                pDevice->readFromXML(xmlReader);
                                //pDevice->initDevice();
                                this->AddDevice(pDevice);
                            }else{
                                qDebug() << "ObjectFactory createObject is NULL!";
                            }
                        }
                    }
                }

                if (xmlReader.isStartElement() && xmlReader.name() == QStringLiteral("Steps")) {
                    while (!(xmlReader.tokenType() == QXmlStreamReader::EndElement
                             && xmlReader.name() == QStringLiteral("Steps"))) {
                        xmlReader.readNext();
                        if (xmlReader.isStartElement()) {
                            QString className = xmlReader.name().toString();
                            Sequence *pSequence = (Sequence *) ObjectFactory::createObject(className.toLatin1(),
                                                                               this);
                            if (pSequence != NULL) {
                                pSequence->readFromXML(xmlReader);
                                this->AddSequence(pSequence);
                            }
                        }
                    }
                }
            }
        }
    }

    // 检查 XML 是否有解析错误
    if (xmlReader.hasError()) {
        qWarning() << "XML error:" << xmlReader.errorString();
    }

    file.close();
    return true;
}

bool Description::writeXML(QXmlStreamWriter &xmlWriter){
    xmlWriter.writeStartElement("Description");
    //////////////////////////////////////////////////////////////
    /// 开始写入内容 devices
    xmlWriter.writeStartElement("Devices");
    foreach (Device *pDevice, m_pDevices) {
        pDevice->writeXML(xmlWriter);
    }
    xmlWriter.writeEndElement();
    //////////////////////////////////////////////////////////////
    /// 开始写入内容 sequences
    xmlWriter.writeStartElement("Sequences");
    foreach (Sequence *pSequence, m_pSequences) {
        pSequence->writeXML(xmlWriter);
    }
    xmlWriter.writeEndElement();
    /////////////////////////////////////////////////////////////
    xmlWriter.writeEndElement();
    return true;
}

bool Description::ReadXML(QXmlStreamReader &xmlReader){
    // 读取 XML 直到结束
    while (!(xmlReader.tokenType() == QXmlStreamReader::EndElement
             && xmlReader.name() == QStringLiteral("Description"))) {
        xmlReader.readNext();
        // 读取所有的设备
        if (xmlReader.isStartElement() && xmlReader.name() == QStringLiteral("Devices")) {
            while (!(xmlReader.tokenType() == QXmlStreamReader::EndElement
                     && xmlReader.name() == QStringLiteral("Devices"))) {
                xmlReader.readNext();
                if (xmlReader.isStartElement()) {
                    QString className = xmlReader.name().toString();
                    Device *pDevice = (Device *) ObjectFactory::createObject(
                        className.toLatin1(),this);
                    if (pDevice != NULL) {
                        pDevice->readFromXML(xmlReader);
                        //pDevice->initDevice();
                        this->AddDevice(pDevice);
                    }else{
                        qDebug() << "ObjectFactory createObject is NULL!";
                    }
                }
            }
        }
        // 读取所有的序列
        if (xmlReader.isStartElement() && xmlReader.name() == QStringLiteral("Sequences")) {
            while (!(xmlReader.tokenType() == QXmlStreamReader::EndElement
                     && xmlReader.name() == QStringLiteral("Sequences"))) {
                xmlReader.readNext();
                if (xmlReader.isStartElement()) {
                    QString className = xmlReader.name().toString();
                    Sequence *pSequence = (Sequence *) ObjectFactory::createObject(className.toLatin1(),this);
                    if (pSequence != NULL) {
                        pSequence->readFromXML(xmlReader);
                        this->AddSequence(pSequence);
                    }
                }
            }
        }
    }

    xmlReader.readNext();
    xmlReader.readNext();
    return true;
}

Device *Description::FindDeviceById(QString strID)
{
    foreach (Device *pDevice, m_pDevices) {
        if (pDevice->getStrID() == strID) {
            return pDevice;
        }
    }

    return NULL;
}

Step* Description::GetStepByImageNum(int number){
    for (int var = 0; var < m_pSequences.count(); ++var) {
        Sequence * pSequence = m_pSequences.at(var);

         QList<Step*> steps = pSequence->GetSteps();
        for(int j = 0 ; j < steps.count(); j ++){
            Step* pStep = steps.at(j);

            QList<Operation*> operations = pStep->GetOperations();

            for(int i = 0; i < operations.count();i++){
                Operation* pOperation = operations.at(i);
                // 找到SnapOperation
                if(pOperation->getClassName() == "SnapOperation"){
                    SnapOperation* pSnapOperation = (SnapOperation*)pOperation;
                    if(pSnapOperation->GetImageNum() == number){
                        return pStep;
                    }
                }
            }
        }
    }
    return NULL;
}

void Description::run()
{
    //initAllDevices();
    m_isRunning = true;

    QThreadPool *threadPool = QThreadPool::globalInstance();
    threadPool->clear();

    for(Sequence* pSequence : m_pSequences){
        StepsThread * pStepsThread = new StepsThread();
        pStepsThread->SetSteps(pSequence->GetSteps());
        pStepsThread->start();
    }
}

void Description::stop(){
    m_isRunning = false;
    //m_DescriptionRunThread->Stop();
}

void Description::test()
{
    initAllDevices();
    uninitAllDevices();
    qDebug() << "Test is finished!";
}

void Description::initAllDevices(){
    if(!m_isAllInitialized){
        foreach (Device *pDevice, m_pDevices) {
            pDevice->initDevice();
        }
        m_isAllInitialized = true;
    }
}

void Description::uninitAllDevices(){
    if(m_isAllInitialized){
        foreach (Device *pDevice, m_pDevices) {
            pDevice->uninitDevice();
        }
        m_isAllInitialized = false;
    }
}

void Description::ReceviceCmdFromVirtualDevice(QVariant variant){
    emit SendCmdToMainWindow(variant);
}
